//-------------------------------------------------------------------
//DATA AND COMMAND FORMAT
//--|BYTE 0|BYTE 1|...
//--BYTE 0	: 0X00-0XFE : COMMAND 1-254
//			: 0XFF		: COMMAND CONTINUES IN NEXT BYTE
//
//MAIN PROGRAM
//LOOP : SEND "REQUEST_STATUS" THIS IS A SLOW LOOP
	//PIC RESPONDS WITH MULTI-BYTE PACKET: |BYTE 1|BYTE 2|...
//IF STATUS="DTS" ( DATA TO SEND) THEN PIC HAS HAD A TIMER TICK AND HAS A BUFFER OF adc VALUES TO SEND
//--SECOND BYTE = NUMBER OF BYTES TO SEND
//--SETUP FAST LOOP
//-----------------------------------------------------------------------
#include "stdafx.h"

// FUNCTIONS  //////////////////////////////////////////////////////////////////////////
void formPacket(int command_length, int *command, byte *packet_tosend, DWORD *packet_tosend_length)
	//
	//Create an SPI waveform to transmit the given command
	//	command_length	:	number of 16 bit words in command sequence
	//	command			:	16 bit integer array,opcode for command
	//	packet_tosend	:	byte array, the SPI signal to send to slave
	//
{
	int i,j;													//loop variables
	int word_length=16;											//number of bits in a data word
	int packet_idx=0;											//current array index of SPI packet
	byte *packet;												//temporary byte array
	packet=new byte[command_length*(word_length*2+10)];			//number of words in command sequence, 16=bits per frame, 2=bytes per SCK cycle, 10= timingbytes added to frames (CLK=0, /CS=0)
	j=0;
	packet[packet_idx++] = (byte)0x08;							//buffer frame, SCK=0, MOSI =0, /CS=1
	for (j=0;j<command_length;j++)								//create a frame for each command word
	{
		packet[packet_idx++] = (byte)0x00;						//buffer frame,SCK=0,MOSI=0,/CS=0 (select slave)
		for (i = word_length-1; i >= 0; i--)						//begin SPI+MOSI clock signal, keep /CS low.  2 frames per clock cycle
		{
																//treat command as a bit sequence, each bit must be transmitted in 1 cycle of SCK
																//Data is clocked into slave at the transition from high to low SCK
																//the final "<<1" shifts the cuurent bit into bit 1 position of the current TX byte
			packet[packet_idx++] = 0x01 | (((command[j] & (1<<i))==(1<<i))<<1);
			packet[packet_idx++] = 0x00 | (((command[j] & (1<<i))==(1<<i))<<1);
		}
		packet[j++] = (byte)0x00;								 //buffer time after last SCK to allow slave to respond
		packet[j++] = (byte)0x00;
		packet[j++] = (byte)0x00;
		packet[j++] = (byte)0x00;
		packet[j++] = (byte)0x00;
		packet[j++] = (byte)0x00;
		packet[j++] = (byte)0x00;
		packet[j++] = (byte)0x08;								// Finall, pull /CS inactive

	}
	packet_tosend=packet;
	*packet_tosend_length=j;
}

void sendPacket(int num_of_symbols, byte *packet_tosend, int packet_tosend_length, int *wordsin, int* wordsinidx, FT_HANDLE ftHandle)
{
	//
	//Write data to slave device and recieve data from slave
	//	num_of_symbols	: number of 16 bit words to send via SPI bus
	//	packet_to_send	: the low level SPI data, with control signals, payload and clock signals.  THere are two bytes sent for eack clock period
	//	packet_to_send_length : Length in bytes of SPI packet, includes timing bytes where there is no clock and /CS islow
	//  wordsin													//holds the data output from FTDI chip

	int bitposition=15;											//DATA IS READ IN FROM SLAVE MSB FORST
	int i,tempsum=0;
	FT_STATUS ftStatus;									
	DWORD BytesWritten=0;
	DWORD TxBytes; 
	DWORD RxBytes; 
	DWORD BytesReceived; 
	DWORD EventDWord;
	byte *RxBuffer;

	//1 bit=1 clock period, which takes 2 bytes to transmit(one byte for high clock, one byte for low clock)
	RxBuffer=new byte[(num_of_symbols)*(16*2+10)];		//number of words to send*(number of bits per word*number of bytes per clock period+number or framing bytes)
	ftStatus = FT_Write(ftHandle, packet_tosend, packet_tosend_length, &BytesWritten); 
	if (ftStatus == FT_OK) { 
	// FT_Write OK 
	} 
	else { 
	// FT_Write Failed 
	} 
	//Find how many bytes have been read
	int cnt=0;
	do
	{  
		FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord); 
		cnt+=1;
	}
	while (RxBytes!= packet_tosend_length);							//pause while FT_GetStatus get's data from FTDI buffers
	if (RxBytes > 0) { 
	  ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived); 
	  if (ftStatus == FT_OK) { 
		// FT_Read OK 
	  } 
	  else { 
		// FT_Read Failed 
	  } 
	} 

	//wordsin=new int[num_of_symbols];							//translate the recieve buffer, extract data
	wordsinidx=new int;
	*wordsinidx=0;
	for (i=1;i<RxBytes;i++)
	{
		//(1<<0): SCK	: BIT 0
		//(1<<1): MOSI	: BIT 1
		//(1<<2): MISO	: BIT 2
		//(1<<3): CS	: BIT 3
		//BITS 4-7 are General purpose IO, not used at the moment
		// read current bit = 1 if previous clock was high, current clock is low, current CS is low else read 0
		if (((RxBuffer[i-1] & (1<<0))==(1<<0)) && ((~RxBuffer[i] & ((1<<0)|(1<<3)))==((1<<0)|(1<<3))))
		{
			tempsum=pow((double)2,bitposition)*((RxBuffer[i] & (1<<2))==(1<<2))+tempsum;// third bit is data input
			bitposition-=1; //count down from MSB to LSB, the order of transmission
		}
		if (bitposition==-1)										//read next 16 bit word from buffer
		{
			wordsin[*wordsinidx]=tempsum;
			*wordsinidx+=1;
			tempsum=0;
			bitposition=15;											//reset counter, there may be more symbols coming
		}
	}
}

// MAIN  ///////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
	byte *packet_tosend;
	DWORD packet_tosend_length=0;
	int *data_from_slave,*command;
	int  command_length,data_from_slave_length;
	FT_STATUS ftStatus;
	FT_HANDLE ftHandle;
	DWORD BytesWritten=0;
	byte* initData;											//configuration opcode for FTDI device
	initData=new byte;
	*initData=0x08;

	ftStatus = FT_Open(0,&ftHandle);							// Open handle to FTDI device
	if(ftStatus != FT_OK) { 
		// FT_Open failed Make some comment
	return 0; 
	}  
	ftStatus = FT_SetBitMode(ftHandle, 0xb, 0x4);				// Setup synchronous bit bang mode mask=b10111=output
	if (ftStatus == FT_OK) { 
	  // 0x0b written to device  
	} 
	else { 
	  // FT_SetBitMode FAILED! 
	} 
	ftStatus = FT_SetBaudRate(ftHandle, 3000000);				// Set baud rate(clock) to 3 MHZ
	  if (ftStatus == FT_OK) { 
		// FT_SetBaudRate OK 
	  } 
	  else { 
		// FT_SetBaudRate Failed 
	  } 
	ftStatus = FT_Write(ftHandle, initData, 1, &BytesWritten);	//Set initial state of pins
	  if (ftStatus == FT_OK) { 
		// FT_Write OK 
	  } 
	  else { 
		// FT_Write Failed 
	  } 
	ftStatus = FT_Purge(ftHandle, FT_PURGE_RX | FT_PURGE_TX);	// Purge both Rx and Tx buffers
	if (ftStatus == FT_OK) { 
		// FT_Purge OK 
	} 
	else { 
		// FT_Purge failed 
	}
// MAIN LOOP  /////////////////////////////////////////////////////////////////////////
	while(1)
	{
// SEND STATUS REQUEST COMMAND  ////////////////////////////////////////////////////////
		command=new int; 
		*command=0x0001;										//REQ_STATUS
		command_length=1;										//IN WORD S
		packet_tosend=new byte[command_length];
		formPacket(command_length,command,packet_tosend,&packet_tosend_length);
		data_from_slave=new int[command_length];
		sendPacket(command_length,packet_tosend,packet_tosend_length, data_from_slave,&data_from_slave_length, ftHandle);
//// SWITCH ON RECIEVED STATUS  /////////////////////////////////////////////////////////
//		switch (data_from_slave)//bits [0-7] of first word
//		{
//			case EXTS:	//0xFF:extended status sequence, read second byte
//				//read bytes until != 0xFF
//				//first byte != 0xFF is the status byte
//				//switch on extended status
//				break;
//			case NOP:	//0x00:No Operation
//				break;
//			case DTS:	//0x01:Data To Send (from slave)
//				slave_data_buff_len=//slave_status[8-15] Read second byte after status byte, it contains the length of buffer in 16 bit words to read
//				command=//REQ_DATA
//				packet_tosend=formPacket(slave_data_buff_len,command);
//				slave_status=sendPacket(&packet_tosend,&data_from_slave); //packet_tosend will contain all the /CS and SCK signals necessary to get buffer_length words fromthe slave
//				if (slave_status=SLAVE_OK)
//				{
//				
//				}
//				else
//				{
//					//Handle PIC data transmission error
//				}
//				break;	
//			default:
//				break;
//		}
	}														//MAIN LOOP
	delete packet_tosend;
	delete data_from_slave;
	delete initData;
	delete command;
	packet_tosend=0;
	data_from_slave=0;
	initData=0;
	command=0;
}